﻿/* ***********************************************
 * Author		:  kingthy
 * Email		:  kingthy@gmail.com
 * Description	:  DbConditionBuilder
 *
 * ***********************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
namespace KT.Framework.Database
{
    /// <summary>
    /// 查询条件的关系
    /// </summary>
    public sealed class DbConditionRelation
    {
        /// <summary>
        /// 条件AND
        /// </summary>
        public const string AND = "AND";
        /// <summary>
        /// 条件OR
        /// </summary>
        public const string OR = "OR";
        /// <summary>
        /// 条件OR
        /// </summary>
        public const string NOT = "NOT";
    }

    /// <summary>
    /// 查询条件构造器
    /// </summary>
    public class DbConditionBuilder
    {
        /// <summary>
        /// 构造默认实例
        /// </summary>
        public DbConditionBuilder()
        {
            this.Builder = new StringBuilder();
            this.Parames = new List<DbParameter>();
        }

        /// <summary>
        /// 
        /// </summary>
        private StringBuilder Builder;

        private List<DbParameter> Parames;
        /// <summary>
        /// 返回相关联参数
        /// </summary>
        public DbParameter[] Parameters
        {
            get
            {
                return Parames.ToArray();
            }
        }


        /// <summary>
        /// 返回条件语句,不带Where,如:Id>1
        /// </summary>
        public string Condition
        {
            get
            {
                if (this.HasCondition)
                {
                    while (ParenthesesCount > 0)
                    {
                        this.EndParentheses();
                    }
                    return Builder.ToString();
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// 是否有条件
        /// </summary>
        public bool HasCondition
        {
            get
            {
                return this.Builder.Length > 0;
            }
        }

        /// <summary>
        /// 括号数量
        /// </summary>
        private int ParenthesesCount = 0;
        /// <summary>
        /// 需要写入的左括号数量
        /// </summary>
        private int NeedWriteLeftParentheses = 0;
        /// <summary>
        /// 已写入的左括号数量
        /// </summary>
        private int WritedLeftParentheses = 0;
        /// <summary>
        /// 开始括号符的写入,即需要写入左括号"("
        /// </summary>
        public void BeginParentheses()
        {
            NeedWriteLeftParentheses++;
            ParenthesesCount++;
        }
        /// <summary>
        /// 结束括号符,即写入右括号")"
        /// </summary>
        public void EndParentheses()
        {
            if (ParenthesesCount > 0)
            {
                if (WritedLeftParentheses > 0)
                {
                    Builder.Append(")");
                    WritedLeftParentheses--;
                }
                ParenthesesCount --;
            }
            this.NeedWriteLeftParentheses = Math.Min(ParenthesesCount, NeedWriteLeftParentheses);
        }
        /// <summary>
        /// 清除括号记录
        /// </summary>
        private void ClearParentheses()
        {
            this.ParenthesesCount = 0;
            this.NeedWriteLeftParentheses = 0;
            this.WritedLeftParentheses = 0;
        }
        /// <summary>
        /// 写入左括号
        /// </summary>
        /// <param name="relation">关系</param>
        private bool WriteLeftParentheses(string relation)
        {
            bool need = NeedWriteLeftParentheses > 0;
            if (need)
            {
                if (this.HasCondition)
                {
                    if (!string.IsNullOrEmpty(relation))
                    {
                        Builder.Append(" ");
                        Builder.Append(relation);
                    }
                    Builder.Append(" ");
                }
                while (NeedWriteLeftParentheses > 0)
                {
                    Builder.Append("(");
                    NeedWriteLeftParentheses--;
                    WritedLeftParentheses++;
                }
            }
            return need;
        }

        /// <summary>
        /// 添加条件
        /// </summary>
        /// <param name="condition">条件,如Id > 1</param>
        public void Add(string condition)
        {
            Add(condition, "AND");
        }
        /// <summary>
        /// 添加条件并带关系
        /// </summary>
        /// <param name="condition">条件,如Id > 1</param>
        /// <param name="relation">与上一个条件的关系,如AND,OR等等</param>
        public void Add(string condition, string relation)
        {
            if (string.IsNullOrEmpty(condition)) throw new ArgumentNullException("condition");
            bool hasLP = this.WriteLeftParentheses(relation);
            if (Builder.Length != 0 && !hasLP)
            {
                Builder.AppendFormat(" {0} ",relation);
            }
            Builder.Append(condition);
        }
        /// <summary>
        /// 添加条件与条件参数
        /// </summary>
        /// <param name="condition">条件,如Id > 1</param>
        /// <param name="pars">相关的参数</param>
        public void Add(string condition,params DbParameter[] pars)
        {
            Add(condition, "AND", pars);
        }
        /// <summary>
        /// 添加条件与条件参数
        /// </summary>
        /// <param name="condition">条件,如Id > 1</param>
        /// <param name="relation">与上一个条件的关系,如AND,OR等等</param>
        /// <param name="pars">相关的参数</param>
        public void Add(string condition, string relation, params DbParameter[] pars)
        {
            Add(condition,relation);
            Parames.AddRange(pars);
        }

        /// <summary>
        /// 添加格式化条件
        /// </summary>
        /// <param name="condition">条件,如Id > {0}</param>
        /// <param name="values">参数值</param>
        public void AddFormat(string condition, params object[] values)
        {
            AddFormat(condition, "AND", values);
        }
        /// <summary>
        /// 添加格式化条件
        /// </summary>
        /// <param name="format">条件,如"Id>{0}"</param>
        /// <param name="value">参数值</param>
        public void AddFormat(string format, string value)
        {
            Add(string.Format(format, value), "AND");
        }
        /// <summary>
        /// 添加格式化条件
        /// </summary>
        /// <param name="condition">条件,如Id > {0}</param>
        /// <param name="relation">与上一个条件的关系,如AND,OR等等</param>
        /// <param name="values">相关值</param>
        public void AddFormat(string condition, string relation, params object[] values)
        {
            Add(string.Format(condition, values), relation);
        }
        /// <summary>
        /// 返回当前的条件语句,如果有条件则语句中带WHERE关键字
        /// </summary>
        /// <returns>如WHERE Id>0</returns>
        public override string ToString()
        {
            string condition = this.Condition;
            if (!string.IsNullOrEmpty(condition))
            {
                return "WHERE " + condition;
            }
            else
            {
                return condition;
            }
        }
        /// <summary>
        /// 清除所有语句
        /// </summary>
        public void Clear()
        {
            this.Builder.Length = 0;
            this.Parames.Clear();
            this.ClearParentheses();
        }
    }
}
